package com.haoyun.mirage.gateway.filter;

import com.haoyun.common.constant.CommonConstant;
import com.haoyun.common.core.http.BaseHttpStatus;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.xiaoleilu.hutool.http.HttpUtil;
import com.xiaoleilu.hutool.io.IoUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.charset.Charset;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.*;

/**
 * Created by twg on 2018/4/15.
 *
 * @see org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter
 */
@Slf4j
@Component
public class RibbonRoutingAfterFilter extends ZuulFilter {
    private static final String DEFAULT_ERROR_MESSAGE = "请求失败，稍后再试！";

    @Override
    public String filterType() {
        return POST_TYPE;
    }

    @Override
    public int filterOrder() {
        return RIBBON_ROUTING_FILTER_ORDER;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        return ctx.get(SERVICE_ID_KEY) != null && ctx.getZuulEngineRan() && BaseHttpStatus.SC_OK != ctx.getResponse().getStatus();
    }

    @Override
    public Object run() {
        log.info("==========This is RibbonRoutingAfterFilter =======");
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletResponse response = context.getResponse();
        log.info("来自IP地址：{}的请求，服务名：{}，请求URI：{}，返回状态：{}", HttpUtil.getClientIP(context.getRequest()),
                context.get(SERVICE_ID_KEY), context.get(REQUEST_URI_KEY), response.getStatus());
        PrintWriter printWriter = null;
        try {
            response.setCharacterEncoding(CommonConstant.UTF8);
            response.setContentType(CommonConstant.CONTENT_TYPE);
            writeResponse(
                    new ByteArrayInputStream(context.getResponseBody().getBytes(Charset.defaultCharset())),
                    response.getOutputStream());
        } catch (Exception e) {
        } finally {
            IoUtil.close(printWriter);
        }
        return null;
    }

    private ThreadLocal<byte[]> buffers = new ThreadLocal<byte[]>() {
        @Override
        protected byte[] initialValue() {
            return new byte[8192];
        }
    };

    private void writeResponse(InputStream zin, OutputStream out) throws Exception {
        byte[] bytes = buffers.get();
        int bytesRead = -1;
        while ((bytesRead = zin.read(bytes)) != -1) {
            out.write(bytes, 0, bytesRead);
        }
    }
}
